package com.uxsino.simo.collector.connections;

import java.lang.reflect.Method;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;

import com.uxsino.simo.connections.AbstractConnection;
import com.uxsino.simo.connections.exception.SimoQueryException;
import com.uxsino.simo.connections.target.TCPTarget;

public class RedisConnection extends AbstractConnection<TCPTarget> {
    private static Logger logger = LoggerFactory.getLogger(RedisConnection.class);

    private Jedis jedis;

    @Override
    public int connect(TCPTarget target) {
        super.connect(target);
        state = 0;
        try {
            jedis = new Jedis(target.host, target.port);
            if (target.getPassword() == null || target.getPassword().length() == 0) {
                connected = true;
                state = 1;
            } else {
                String authRes = jedis.auth(target.getPassword());
                if (authRes.equals("OK")) {
                    connected = true;
                    state = 1;
                } else {
                    logger.error("redis conneciton authentication failed");
                }
            }
        } catch (Exception e) {
            logger.error("redis connect error: {}", e);
        }

        /*
        if no auth use:
        connected = true;
        logger.info("connect: " + connected);
        */
        return state;
    }

    @Override
    public Object execCmd(Object cmd) throws SimoQueryException {
        String cmdStr = (String) cmd;
        String[] cmdArr = cmdStr.split(" ");

        Class<?>[] params = null;
        Object[] args = null;
        if (cmdArr.length == 1) {
            params = new Class[0];
            args = new Object[0];
        } else {
            params = new Class[1];
            params[0] = String.class;
            args = new Object[1];
            args[0] = cmdArr[1];
        }

        String resStr = null;
        try {
            Method method = jedis.getClass().getMethod(cmdArr[0], params);
            resStr = (String) method.invoke(jedis, args);
        } catch (Exception e) {
            logger.error(cmdStr, e);
            throw new SimoQueryException(e);
        }

        return resStr;
    }

    @Override
    public Object buildCmd(String cmdPattern, Map<String, String> args) {
        return cmdPattern;
    }

    @Override
    public int close() {
        if (connected && jedis != null) {
            try {
                jedis.close();
            } catch (Exception e) {
                logger.error("close jedis connection error: ", e);
            }
        }
        connected = false;
        super.close();
        return 0;
    }

    @Override
    public boolean testWithConnected(String cmdString, String resStart) {
        connected = false;
        try {
            if (resStart.startsWith("indexOf:")) {
                String resStr = resStart.substring(8);
                String res = (String) execCmd(cmdString);
                if (res != null && res.indexOf(resStr) != -1) {
                    connected = true;
                }
            } else if (resStart.startsWith("startsWith:")) {
                String resStr = resStart.substring(11);
                String res = (String) execCmd(cmdString);
                if (res != null && res.startsWith(resStr)) {
                    connected = true;
                }
            }
        } catch (SimoQueryException e) {
            logger.error("execute command failed : {}", e);
        }
        logger.info("redis connectionTest result {}", connected);
        return connected;
    }

}
